using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using NUnit.Framework;
using Wax;
using Wax.Runner;

namespace WaxRunnerTest
{
    /// <summary>
    /// Test all the behaviour of the TestRunner class
    /// </summary>
    [TestFixture]
    public class TestRunnerTest
    {
        #region Private readonly fields

        /// <summary>
        /// Filename of test script
        /// </summary>
        private readonly string FileName = Path.Combine(Environment.CurrentDirectory, "exampletest.xlsx");

        #endregion

        #region Public test methods

        /// <summary>
        /// Tests the Contructors.
        /// </summary>
        [Test]
        public void ContructorTest()
        {
            TestRunner testRunner = new TestRunner();
            Assert.IsNull(testRunner.FileName);
            Assert.IsNotNull(testRunner.AllowedFileExtensions, "AllowedFileExtensions found to be null");
        }

        /// <summary>
        /// Tests the second constructor.
        /// </summary>
        [Test]
        public void ContructorTest2()
        {
            TestRunner testRunner = new TestRunner(FileName);
            Assert.AreEqual(testRunner.FileName, FileName);
            Assert.IsNotNull(testRunner.AllowedFileExtensions);
        }

        /// <summary>
        /// Tests that when a file that does not exist is passed into the constructor, a <see cref="FileNotFoundException"/> 
        /// exception is thrown
        /// </summary>
        [Test, ExpectedException(typeof(FileNotFoundException))]
        public void ConstructorFileNotFound()
        {
            TestRunner testRunner = new TestRunner(@"c:\notexits\fileneverexists.ever");
        }

        /// <summary>
        /// Tests for unsupported file types.
        /// </summary>
        [Test, ExpectedException(typeof(ArgumentException))]
        public void ConstructorInvalidFileType()
        {
            TestRunner testRunner = new TestRunner(Path.Combine(Environment.CurrentDirectory, "testpage1.htm"));
        }

        /// <summary>
        /// Tests the behaviour of the <see cref="TestRunner.Load"/> method.
        /// </summary>
        [Test]
        public void LoadTest()
        {
            TestRunner testRunner = new TestRunner(FileName);
            testRunner.Load();

            // Assert the number of tests loaded
            Assert.AreEqual(2, testRunner.Tests.Count, "Incorrect number of tests parsed");

            // Assert the test attributes have been correclty loaded
            Assert.AreEqual("test1", testRunner.Tests[0].Id, "Invalid test id found.");
            Assert.AreEqual("2", testRunner.Tests[1].Id, "Invalid test id found.");

            // Assert the commands in the first test have been correctly loaded
            Assert.AreEqual(2, testRunner.Tests[0].Commands.Count, string.Format("Incorrect number of commands parsed for test with id {0}", testRunner.Tests[0].Id));

            Command command = testRunner.Tests[0].Commands[0];
            Assert.AreEqual(CommandType.GoTo, command.CommandType, "Incorrect command type found in first test");
            Assert.AreEqual("GotoHome", command.Id, "Incorrect command id found in first test");
            Assert.AreEqual("http://www.google.co.uk", command.Arguments[0], "Incorrect command arguments found in first test");

            Assert.AreEqual(1, testRunner.Tests[1].Commands.Count, string.Format("Incorrect number of commands parsed for test with id {0}", testRunner.Tests[1].Id));
            command = testRunner.Tests[1].Commands[0];
            Assert.AreEqual(CommandType.GoTo, command.CommandType, "Incorrect command type found in second test");
            Assert.AreEqual("GotoHome2", command.Id, "Incorrect command id found in second test");
            Assert.AreEqual("testpage2.htm", command.Arguments[0], "Incorrect command arguments found in second test");
        }


        private int progressHandlerCalledCount;

        /// <summary>
        /// Tests the behaviour of the <see cref="TestRunner.Progress"/> event.
        /// </summary>
        [Test]
        public void ProgressTest()
        {
            TestRunner testRunner = new TestRunner(FileName);
            testRunner.Load();
            testRunner.Progress += new EventHandler<TestProgressEventArgs>(TestRunnerProgress);

            this.progressHandlerCalledCount = 0;

            testRunner.Execute();

            Assert.AreEqual(3, this.progressHandlerCalledCount, "The progress event was not fired the expected number of times.");
        }

        /// <summary>
        /// Handles the Progress event of the testRunner control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="TestProgressEventArgs"/> instance containing the event data.</param>
        private void TestRunnerProgress(object sender, TestProgressEventArgs e)
        {
            this.progressHandlerCalledCount = this.progressHandlerCalledCount + 1;
        }

        #endregion

    }
}
